package com.ff.kvm.team.service.impl;

import com.ff.kvm.common.dv.es.UserESDV;
import com.ff.kvm.common.dv.es.UserESLVDV;
import com.ff.kvm.common.eunm.UserTeamGiftLvEnum;
import com.ff.kvm.common.eunm.UserTeamProductLvEnum;
import com.ff.kvm.common.util.Constants;
import com.ff.kvm.common.util.ConvertUtil;
import com.ff.kvm.common.util.ResponseUtil;
import com.ff.kvm.common.vo.Response;
import com.ff.kvm.dao.mapper.TeamMapper;
import com.ff.kvm.dao.mapper.UserMapper;
import com.ff.kvm.dao.model.Team;
import com.ff.kvm.dao.model.User;
import com.ff.kvm.team.es.entity.UserES;
import com.ff.kvm.team.es.repository.ESUserRepository;
import com.ff.kvm.team.es.util.ESUtil;
import com.ff.kvm.team.service.RedisService;
import com.ff.kvm.team.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private ESUserRepository userRepository;

    @Autowired
    private RedisService redisService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private TeamMapper teamMapper;

    @Override
    public Response<Boolean> addUser(UserESDV userESDV) {
        userRepository.save(ConvertUtil.convert(userESDV, UserES.class));
        return ResponseUtil.success();
    }

    @Override
    public List<UserES> findUserESByFloor(int floor) {

        return userRepository.search(ESUtil.getSearchQuery(ESUtil.getBoolQueryBuilder("floor",floor))).getContent();
    }

    @Override
    public UserES findUserESById(int userId) {
        return userRepository.search(ESUtil.getSearchQuery(ESUtil.getBoolQueryBuilder("userId",userId))).getContent().get(0);
    }

    @Override
    public Response<Boolean> updateUserLv(UserESDV userESDV) {
        UserES userES = findUserESById(userESDV.getUserId());
        userES.setLv(userESDV.getLv());
        userES.setTeamGiftLv(userESDV.getTeamGiftLv());
        userES.setTeamProductLv(userESDV.getTeamProductLv());
        userRepository.save(userES);
        return ResponseUtil.success();
    }


    @Override
    public String[] getGiftBoxTeamCF() {
        String[] cf = new String[7];
        cf[0] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+1);
        cf[1] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+2);
        cf[2] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+3);
        cf[3] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+4);
        cf[4] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+5);
        cf[5] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+6);
        cf[6] = redisService.getCache(Constants.GIFT_BOX_BONUS_CF+7);
        return cf;
    }

    @Override
    public String[] getProdctTeamCF() {
        String[] cf = new String[4];
        cf[0] = redisService.getCache(Constants.PRODUCT_BONUS_CF+1);
        cf[1] = redisService.getCache(Constants.PRODUCT_BONUS_CF+2);
        cf[2] = redisService.getCache(Constants.PRODUCT_BONUS_CF+3);
        cf[3] = redisService.getCache(Constants.PRODUCT_BONUS_CF+4);
        return cf;
    }


    @Override
    public void exeUserLV() {
        log.info("执行全网用户等级计算...start");
        //会员总结构,计算所有人的等级
        int floor = userMapper.getMaxFloor();
        String[] giftCf = getGiftBoxTeamCF();
        String[] productCf = getProdctTeamCF();
        Map<Integer, UserESLVDV> all = new HashMap<>();
//        int giftLv = Integer.valueOf(redisService.getCache(Constants.GIFT_BOX_BONUS_LV));
//        int productLv = Integer.valueOf(redisService.getCache(Constants.PRODUCT_BONUS_LV));
        for(int i = floor;i>0;i--){
            sumUserLv(i,all,giftCf,productCf);
        }
        log.info("执行全网用户等级计算...end");
    }


    private void sumUserLv(int floor, Map<Integer, UserESLVDV> all, String[] giftCf, String[] productCf) {
        List<UserES> list = findUserESByFloor(floor);
        for (UserES userES : list){
            UserESLVDV user = new UserESLVDV();
            if(all.containsKey(userES.getUserId())){
                user = all.get(userES.getUserId());
            }
            user.setUpUserId(userES.getUpUserId());
            user.setUserId(userES.getUserId());
            user.setLv(userES.getLv());
            user.setTeamGiftLV(userES.getTeamGiftLv());
            user.setTeamProductLV(userES.getTeamProductLv());

            //计算当前用户的礼包分红等级
            setTeamGiftLV(user,giftCf,userES);
            //计算当前用户的商品重销等级
            setTeamProductLV(user,productCf,userES);

            UserESLVDV upUser = new UserESLVDV();
            upUser.setUserId(userES.getUpUserId());
            //查看是否存在上级
            if(userES.getUpUserId() != 0 && all.containsKey(userES.getUpUserId())){
                upUser = all.get(userES.getUpUserId());
            }

            //将当前用户放入上级直推
            setDirect(user,upUser);

            //将当前用户的伞下用户放入上级伞下
            setTree(user,upUser);

            all.put(userES.getUpUserId(),upUser);

            updateUserTeam(user);

            if(all.containsKey(userES.getUserId())){
                all.remove(userES.getUserId());
            }

        }
    }


    private void setDirect(UserESLVDV user,UserESLVDV upUser) {
        //用户身份
        setDirect(user.getLv(),upUser);

        //礼包分红:按照当前用户的星级分别加入上级直推
        setGiftDirect(user.getTeamGiftLV(),upUser);

        //商品分红:按照当前用户的等级级分别加入上级直推
        setProductDirect(user.getTeamProductLV(),upUser);
    }

    private void setProductDirect(int lv, UserESLVDV upUser) {
        switch (lv){
            case 1:upUser.setDplv1(upUser.getDplv1() + 1);break;
            case 2:upUser.setDplv2(upUser.getDplv2() + 1);break;
            case 3:upUser.setDplv3(upUser.getDplv3() + 1);break;
            case 4:upUser.setDplv4(upUser.getDplv4() + 1);break;
        }
    }

    private void setGiftDirect(int lv, UserESLVDV upUser) {
        switch (lv){
            case 1: upUser.setDglv1(upUser.getDglv1()+1);break;
            case 2: upUser.setDglv2(upUser.getDglv2()+1);break;
            case 3: upUser.setDglv3(upUser.getDglv3()+1);break;
            case 4: upUser.setDglv4(upUser.getDglv4()+1);break;
            case 5: upUser.setDglv5(upUser.getDglv5()+1);break;
            case 6: upUser.setDglv6(upUser.getDglv6()+1);break;
            case 7: upUser.setDglv7(upUser.getDglv7()+1);break;
        }
    }

    private void setDirect(int lv,UserESLVDV upUser) {
        switch (lv){
            case 0:upUser.setDlv0(upUser.getDlv0() + 1);break;
            case 1:upUser.setDlv1(upUser.getDlv1() + 1);break;
            case 2:upUser.setDlv2(upUser.getDlv2() + 1);break;
            case 3:upUser.setDlv3(upUser.getDlv3() + 1);break;
        }
    }

    private void setTree(UserESLVDV user,UserESLVDV upUser) {

        //用户身份
        setUserTree(user,upUser);

        //礼包分红:将当前用户的直推和伞下加入上级伞下
        setGiftTree(user,upUser);

        //商品分红:将当前用户的直推和伞下加入上级伞下
        setProductTree(user,upUser);
    }

    private void setProductTree(UserESLVDV user, UserESLVDV upUser) {

        upUser.setTplv1(upUser.getTplv1() + user.getDplv1() + user.getTplv1());
        upUser.setTplv2(upUser.getTplv2() + user.getDplv2() + user.getTplv2());
        upUser.setTplv3(upUser.getTplv3() + user.getDplv3() + user.getTplv3());
        upUser.setTplv4(upUser.getTplv4() + user.getDplv4() + user.getTplv4());
    }

    private void setGiftTree(UserESLVDV user, UserESLVDV upUser) {
        upUser.setTglv1(upUser.getTglv1() + user.getDglv1() + user.getTglv1());
        upUser.setTglv2(upUser.getTglv2() + user.getDglv2() + user.getTglv2());
        upUser.setTglv3(upUser.getTglv3() + user.getDglv3() + user.getTglv3());
        upUser.setTglv4(upUser.getTglv4() + user.getDglv4() + user.getTglv4());
        upUser.setTglv5(upUser.getTglv5() + user.getDglv5() + user.getTglv5());
        upUser.setTglv6(upUser.getTglv6() + user.getDglv6() + user.getTglv6());
        upUser.setTglv7(upUser.getTglv7() + user.getDglv7() + user.getTglv7());
    }

    private void setUserTree(UserESLVDV user, UserESLVDV upUser) {
        upUser.setTlv0(upUser.getTlv0() + user.getDlv0() + user.getTlv0());
        upUser.setTlv1(upUser.getTlv1() + user.getDlv1() + user.getTlv1());
        upUser.setTlv2(upUser.getTlv2() + user.getDlv2() + user.getTlv2());
        upUser.setTlv3(upUser.getTlv3() + user.getDlv3() + user.getTlv3());
    }

    private void setTeamGiftLV(UserESLVDV user,String[] cf,UserES userES) {
        if(userES.getTeamGiftLv() == UserTeamGiftLvEnum.STAR7.type()){
            return;
        }
        //直接开通的等级
        int lv = 0;
        for (int i = cf.length-1;i>= user.getTeamGiftLV();i--){
            lv = checkTeamGiftLV(user,cf[i],i+1);
            if(lv != 0){
                break;
            }
        }

        if(lv > userES.getTeamGiftLv()){
            userES.setTeamGiftLv(lv);
            user.setTeamGiftLV(lv);
            userRepository.save(userES);
            updateUserTeamGiftLv(userES.getUserId(),lv);
        }
    }


    private void updateUserTeamGiftLv(int userId, int lv) {
        userMapper.updateUserTeamGiftLv(userId,lv);
    }


    private void updateUserTeamProductLv(int userId, int lv) {
        userMapper.updateUserTeamProductLv(userId,lv);
    }

    private void setTeamProductLV(UserESLVDV user,String[] cf,UserES userES) {
        if(userES.getTeamProductLv() == UserTeamProductLvEnum.LV4.type()){
            return;
        }
        int lv = 0;
        for (int i=cf.length-1;i>=userES.getTeamProductLv();i--){
            String[] lvstr = cf[i].split("-");
            if(user.getDlv3() >= Integer.valueOf(lvstr[0]) && user.getTlv3() >= Integer.valueOf(lvstr[1])){
                lv = i+1;
                break;
            }
        }

        if(lv > userES.getTeamProductLv()){
            userES.setTeamProductLv(lv);
            user.setTeamProductLV(lv);
            userRepository.save(userES);
            updateUserTeamProductLv(userES.getUserId(),lv);
        }
    }



    private int checkTeamGiftLV(UserESLVDV user, String cfstr,int lv) {

        String[] cf = cfstr.split("-");
        if(user.getDirect2() >= Integer.valueOf(cf[0]) ){
            switch (lv){
                case 1: return checkStar(user.getTree(),Integer.valueOf(cf[2]),lv);
                case 2: return checkStar(user.getTree(),Integer.valueOf(cf[2]),lv);
                case 3: return checkStar(user.getTree(),Integer.valueOf(cf[2]),lv);
                case 4: return checkStar(user.getTree(),Integer.valueOf(cf[2]),lv);
                case 5: return checkStar(user.getGift4Tree(),Integer.valueOf(cf[2]),lv);
                case 6: return checkStar(user.getGift5Tree(),Integer.valueOf(cf[2]),lv);
                case 7: return checkStar(user.getGift6Tree(),Integer.valueOf(cf[2]),lv);
                default:
                    return 0;
            }
        }
        return 0;
    }

    private int checkStar(int people, int star,int lv) {
        if(people >= star){
            return lv;
        }
        return 0;
    }


    private void updateUserTeam(UserESLVDV user) {
        Team team = new Team();
        team.setUserId(user.getUserId());
        team.setUpUserId(user.getUpUserId());
        team.setLv(user.getLv());
        team.setgLv(user.getTeamGiftLV());
        team.setpLv(user.getTeamProductLV());
        team.setdLv0(user.getDlv0());
        team.setdLv1(user.getDlv1());
        team.setdLv2(user.getDlv2());
        team.setdLv3(user.getDlv3());

        team.settLv0(user.getTlv0());
        team.settLv1(user.getTlv1());
        team.settLv2(user.getTlv2());
        team.settLv3(user.getTlv3());

        team.setdGLv1(user.getDglv1());
        team.setdGLv2(user.getDglv2());
        team.setdGLv3(user.getDglv3());
        team.setdGLv4(user.getDglv4());
        team.setdGLv5(user.getDglv5());
        team.setdGLv6(user.getDglv6());
        team.setdGLv7(user.getDglv7());

        team.settGLv1(user.getTglv1());
        team.settGLv2(user.getTglv2());
        team.settGLv3(user.getTglv3());
        team.settGLv4(user.getTglv4());
        team.settGLv5(user.getTglv5());
        team.settGLv6(user.getTglv6());
        team.settGLv7(user.getTglv7());

        team.setdPLv1(user.getDplv1());
        team.setdPLv2(user.getDplv2());
        team.setdPLv3(user.getDplv3());
        team.setdPLv4(user.getDplv4());

        team.settPLv1(user.getTplv1());
        team.settPLv2(user.getTplv2());
        team.settPLv3(user.getTplv3());
        team.settPLv4(user.getTplv4());

        Integer id = teamMapper.getIdByUserId(user.getUserId());
        if(id == null){
            teamMapper.insert(team);
        }else {
            team.setId(id);
            team.setUpdateTime(new Date());
            teamMapper.updateByPrimaryKey(team);
        }
    }

    @Override
    public Response<Boolean> updateUser(int userId) {
        User user = userMapper.findNormalUser(userId);
        Integer upUserId = userMapper.getIdByUserCode(user.getPollCode());
        UserES userES = new UserES();
        userES.setUserId(userId);
        userES.setUpUserId(upUserId == null ?0:upUserId);
        userES.setLv(user.getLv());
        userES.setTeamGiftLv(user.getTeamGiftLv());
        userES.setTeamProductLv(user.getTeamProductLv());
        userES.setFloor(user.getFloor());
        userES.setStatus(user.getStatus());
        userES.setCreateTime(user.getCreateTime());
        userRepository.save(userES);
        return ResponseUtil.success();
    }

    public Response<Boolean> updateAllUser() {
        List<Integer> list = userMapper.findUserIds();
        for (Integer id : list){
            User user = userMapper.findNormalUser(id);
            Integer upUserId = userMapper.getIdByUserCode(user.getPollCode());

            UserES userES = new UserES();
            userES.setUserId(id);
            userES.setUpUserId(upUserId == null ?0:upUserId);
            userES.setLv(user.getLv());
            userES.setTeamGiftLv(user.getTeamGiftLv());
            userES.setTeamProductLv(user.getTeamProductLv());
            userES.setFloor(user.getFloor());
            userES.setStatus(user.getStatus());
            userES.setCreateTime(user.getCreateTime());
            userRepository.save(userES);
        }

        return ResponseUtil.success();
    }

    @Override
    public int getMaxFloor() {
        return userMapper.getMaxFloor();
    }


    @Override
    public Response<Boolean> executeLV() {
        new Runnable() {
            @Override
            public void run() {
                exeUserLV();
            }
        };
        return ResponseUtil.success();
    }
}
